package turtle.system.pt;

import java.io.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import arbor.mining.util.date.DateUtil;
import arbor.mining.util.stock.StockEntity;
import turtle.system.util.*;
/**
 * 用來判斷兩方法之共同獲利 請先執行DailyExec/DailyStopProfitExec 結果放在tmp/history_profit.csv
 * 
 * @author doug
 * 
 */
public class DailyStopProfitLossEvaluator {
	// 尋找手上無單的開始時間
	// public static final String START_TIME = "2009/02/09";
	public static final String START_TIME = "1999/01/05";
	// public static final String START_TIME = "2008/01/21";
	// public static final String START_TIME = "2006/02/15";
	// public static final String START_TIME = "2006/02/15";
	// public static final String START_TIME = "2000/03/14";
	// public static final String START_TIME = "1999/12/01";
	public static final String END_TIME = "2009/04/02";
	public static final boolean COUNT_FOUR_STRATEGIES = false;
	public static final boolean LOAD_PT_RESULT = false;
	private static final DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
	public final String HISTORY_FN = "tmp/history_profit.csv";
	TreeMap<String, Double> dayMap = new TreeMap<String, Double>();
	TreeMap<String, StockEntity> allStockPrices = DailyExec
			.getAllStockData(DailyExec.WTX1_PREFIX_FN + DailyExec.FN_SUFFIX);

    public int getLotByProfit(double curProfit) {
    	int lot = ((int)curProfit/3000);
    	if (lot<1)
    		lot = 1;
    	if (lot > 30)
    		lot = 30;
    	return lot;
    }
	public int getLot(GregorianCalendar start, String date) {
		GregorianCalendar cur = new GregorianCalendar();
		GregorianCalendar comp = (GregorianCalendar) start.clone();
		int lot = 1;
		try {
			cur.setTime(df.parse(date));
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		comp.add(Calendar.YEAR, 1);
		while (cur.after(comp)) {
			comp.add(Calendar.YEAR, 1);
			lot = lot * 2;
		}
		if (lot > 32)
			lot = 32;
		lot = 1;
		return lot;
	}

	public void exec() throws IOException {
		int currentLot = 1;
		double[] inPrice = new double[4];
		int[] longOrShort = new int[4];
		int[] forceLoss = new int[4];
		ArrayList<Trade> tradeList0 = new ArrayList<Trade>();
		ArrayList<Trade> tradeList1 = new ArrayList<Trade>();
		BufferedWriter writer = new BufferedWriter(new FileWriter(HISTORY_FN));
		TreeMap<String, ArrayList<Action>> map0 = null;
		TreeMap<String, ArrayList<Action>> map1 = null;
		prevActionType = -1;
		map0 = readFile(PriceDataForceLossStopProfit.CONS_FN, tradeList0);
		forceLoss[0] = PriceDataForceLossStopProfit.FORCE_STOPLOSS_CONSERVATIVE;
		//map0 = readFile(PriceDataForceLossStopProfit.POSI_FN, tradeList0);
		//forceLoss[0] = PriceDataForceLossStopProfit.FORCE_STOPLOSS_POSITIVE;		
		prevActionType = -1;
		//map1 = readFile(PriceDataForceLossStopProfit.POSI_FN,tradeList1);
		//forceLoss[1] = PriceDataForceLossStopProfit.FORCE_STOPLOSS_POSITIVE;

		TreeMap<String, ArrayList<Action>> map2 = null;
		TreeMap<String, ArrayList<Action>> map3 = null;
		if (COUNT_FOUR_STRATEGIES) {
			prevActionType = -1;
			map2 = readFile(PriceDataForceLossStopProfit.CONS_FN, null);
			forceLoss[2] = PriceDataForceLossStopProfit.FORCE_STOPLOSS_CONSERVATIVE;
			prevActionType = -1;
			map3 = readFile(PriceDataForceLossStopProfit.POSI_FN, null);
			forceLoss[3] = PriceDataForceLossStopProfit.FORCE_STOPLOSS_POSITIVE;
		}
		GregorianCalendar start = new GregorianCalendar();
		GregorianCalendar end = new GregorianCalendar();
		GregorianCalendar iterTime = new GregorianCalendar();

		int numInHand = 0; /* 正代表多單數，負代表空單數，0為沒單 */
		double currentProfit = 0;
		try {
			start.setTime(df.parse(START_TIME));
			end.setTime(df.parse(END_TIME));
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		iterTime.setTime(start.getTime());
		String iterString = df.format(iterTime.getTime());
		double prevClosePrice = allStockPrices.get(iterString).ohlc.close;

		while (!iterTime.after(end)) {
			iterString = df.format(iterTime.getTime());
			currentLot = getLot(start, iterString);
			//currentLot = getLotByProfit(currentProfit);
			if (!allStockPrices.containsKey(iterString)) {
				iterTime.add(Calendar.DATE, 1);
				continue; /* 沒開市 */
			}
			if (map0.containsKey(iterString)) {
                boolean moreThanOneTradeinDay =false;
				ArrayList<Action> alist = map0.get(iterString);
				if (alist.size()>1) { /*開盤買進,盤中即出場*/
					moreThanOneTradeinDay = true;
				}
				else {
					moreThanOneTradeinDay = false;
				}
				for (int i = 0; i < alist.size(); i++) {
					Action act = alist.get(i);
					if (act.inOrOut == Action.IN_ACTION
							&& (act.longOrShort == Action.LONG_ACTION || 
							act.longOrShort == Action.LONG_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN)) {
						inPrice[0] = act.price;
						longOrShort[0] = Action.LONG_ACTION;
						if (act.longOrShort == Action.LONG_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN){
							  currentProfit += currentLot
								* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);							
						}
						/* 開盤即買進 */
						if (moreThanOneTradeinDay)
						{							
							;				
						}
						else {
						  currentProfit += currentLot
								* (allStockPrices.get(iterString).ohlc.close - allStockPrices
										.get(iterString).ohlc.open);
						}
						numInHand++;
					} else if (act.inOrOut == Action.OUT_ACTION
							&& act.longOrShort == Action.LONG_ACTION) {
						if (act.reason == Action.STOP_LOSS_REASON) {
							/* 停損單尾盤賣出 */
							currentProfit += currentLot
									* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
						} else if (act.reason == Action.STOP_PROFIT_REASON) {
							/* 停利單開盤賣出 */
							currentProfit += currentLot
									* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
						} else if (act.reason == Action.TREND_REVERT_REASON) {
							/* 多單趨勢反轉,選擇開盤賣出 */
							currentProfit += currentLot
									* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);						
						} else if (act.reason == Action.FORCE_STOP_LOSS_REASON) {
							/* 盤中強制出場 */
							double sellprice = inPrice[0] - forceLoss[0];
							if (moreThanOneTradeinDay)
							{
								currentProfit -= currentLot*forceLoss[0];
							}
							else {
								currentProfit += currentLot							
									* (sellprice - prevClosePrice);
							}
						} else if (act.reason == Action.FORCE_STOP_LOSS_AT_START_REASON) {
							/* 盤中開盤強制出場 */							
							currentProfit += currentLot
									* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
						}

						inPrice[0] = -1;
						longOrShort[0] = -1;
						numInHand--;
					} else if (act.inOrOut == Action.IN_ACTION
							&& (act.longOrShort == Action.SHORT_ACTION 
									|| act.longOrShort == Action.SHORT_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN)) {
						/* 開盤即放空 */
						inPrice[0] = act.price;
						longOrShort[0] = Action.SHORT_ACTION;
						if (act.longOrShort == Action.SHORT_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN){
							  currentProfit += currentLot
								* (prevClosePrice-allStockPrices.get(iterString).ohlc.open);							
						}
						if (moreThanOneTradeinDay)
						{
							;					
						}
						else  {
						currentProfit -= currentLot
								* (allStockPrices.get(iterString).ohlc.close - allStockPrices
										.get(iterString).ohlc.open);
						}
						numInHand--;
					} else if (act.inOrOut == Action.OUT_ACTION
							&& act.longOrShort == Action.SHORT_ACTION) {
						if (act.reason == Action.STOP_LOSS_REASON) {
							/* 尾盤回補 */
							currentProfit -= currentLot
									* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
						} else if (act.reason == Action.STOP_PROFIT_REASON
								|| act.reason == Action.TREND_REVERT_REASON) {
							/* 開盤即空單回補 */
							currentProfit -= currentLot
									* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
						} else if (act.reason == Action.FORCE_STOP_LOSS_REASON) {
							/* 盤中強制出場 */
							double sellprice = inPrice[0] + forceLoss[0];
							if (moreThanOneTradeinDay)
							{
								currentProfit -= currentLot*forceLoss[0];
								//currentProfit += currentLot
								//* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);								
							}
							else {							
							  currentProfit -= currentLot
									* (sellprice - prevClosePrice);
							}
						} else if (act.reason == Action.FORCE_STOP_LOSS_AT_START_REASON) {
							/* 盤中開盤強制出場 */
							currentProfit -= currentLot
									* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
						}
						inPrice[0] = -1;
						longOrShort[0] = -1;
						numInHand++;
					} else {
						System.err.println("ERROR TYPE I");
						System.exit(0);
					}
				}
			} else {
				/* 此日無動作,保有原單 */
				if (inPrice[0] < 0 || longOrShort[0] == -1) {
					; // do nothing
				} else if (longOrShort[0] == Action.LONG_ACTION)
					currentProfit += currentLot
							* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
				else if (longOrShort[0] == Action.SHORT_ACTION)
					currentProfit -= currentLot
							* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
				else if (longOrShort[0] == 0) {
					; // do nothing
				} else {
					System.err.println("ERROR TYPE III");
				}

			}
			if (map1 != null) {
				if (map1.containsKey(iterString)) {
					
	                boolean moreThanOneTradeinDay =false;
					ArrayList<Action> alist = map1.get(iterString);
					if (alist.size()>1) { /*開盤買進,盤中即出場*/
						moreThanOneTradeinDay = true;
					}
					else {
						moreThanOneTradeinDay = false;
					}
					for (int i = 0; i < alist.size(); i++) {
						Action act = alist.get(i);

						if (act.inOrOut == Action.IN_ACTION
								&& act.longOrShort == Action.LONG_ACTION) {
							inPrice[1] = act.price;
							longOrShort[1] = Action.LONG_ACTION;
							/* 開盤即買進 */
							if (moreThanOneTradeinDay)
							{							
								;				
							}
							else {
							  currentProfit += currentLot
									* (allStockPrices.get(iterString).ohlc.close - allStockPrices
											.get(iterString).ohlc.open);
							}
							numInHand++;
						} else if (act.inOrOut == Action.OUT_ACTION
								&& act.longOrShort == Action.LONG_ACTION) {
							if (act.reason == Action.STOP_LOSS_REASON) {
								/* 尾盤賣出 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
							} else if (act.reason == Action.STOP_PROFIT_REASON
									|| act.reason == Action.TREND_REVERT_REASON) {
								/* 開盤即賣出 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							} else if (act.reason == Action.FORCE_STOP_LOSS_REASON) {
								/* 盤中強制出場 */
								double sellprice = inPrice[1] - forceLoss[1];
								if (moreThanOneTradeinDay)
								{
									currentProfit -= currentLot*forceLoss[1];
								}
								else {
									currentProfit += currentLot							
										* (sellprice - prevClosePrice);
								}
							} else if (act.reason == Action.FORCE_STOP_LOSS_AT_START_REASON) {
								/* 盤中開盤強制出場 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							}

							inPrice[1] = -1;
							longOrShort[1] = -1;
							numInHand--;
						} else if (act.inOrOut == Action.IN_ACTION
								&& act.longOrShort == Action.SHORT_ACTION) {
							/* 開盤即放空 */
							inPrice[1] = act.price;
							longOrShort[1] = Action.SHORT_ACTION;
							if (moreThanOneTradeinDay)
							{
								;					
							}
							else  {
							currentProfit -= currentLot
									* (allStockPrices.get(iterString).ohlc.close - allStockPrices
											.get(iterString).ohlc.open);
							}							numInHand--;
						} else if (act.inOrOut == Action.OUT_ACTION
								&& act.longOrShort == Action.SHORT_ACTION) {
							if (act.reason == Action.STOP_LOSS_REASON) {
								/* 尾盤回補 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
							} else if (act.reason == Action.STOP_PROFIT_REASON
									|| act.reason == Action.TREND_REVERT_REASON) {
								/* 開盤即空單回補 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							} else if (act.reason == Action.FORCE_STOP_LOSS_REASON) {
								/* 盤中強制出場 */
								double sellprice = inPrice[1] + forceLoss[1];
								if (moreThanOneTradeinDay)
								{
									currentProfit -= currentLot*forceLoss[1];
									//currentProfit += currentLot
									//* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);								
								}
								else {							
								  currentProfit -= currentLot
										* (sellprice - prevClosePrice);
								}
							} else if (act.reason == Action.FORCE_STOP_LOSS_AT_START_REASON) {
								/* 盤中開盤強制出場 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							}
							inPrice[1] = -1;
							longOrShort[1] = -1;
							numInHand++;
						} else {
							System.err.println("ERROR TYPE IV");
							System.exit(0);
						}
					}
				} else {
					/* 此日無動作,保有原單 */
					if (inPrice[1] < 0 || longOrShort[1] == -1) {
						; // do nothing
					} else if (longOrShort[1] == Action.LONG_ACTION)
						currentProfit += currentLot
								* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
					else if (longOrShort[1] == Action.SHORT_ACTION)
						currentProfit -= currentLot
								* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
					else if (longOrShort[1] == 0) {
						; // do nothing
					} else {
						System.err.println("ERROR TYPE III");
					}
				}
			}

			if (map2 != null) {
				if (map2.containsKey(iterString)) {
	                boolean moreThanOneTradeinDay =false;
					ArrayList<Action> alist = map2.get(iterString);
					if (alist.size()>1) { /*開盤買進,盤中即出場*/
						moreThanOneTradeinDay = true;
					}
					else {
						moreThanOneTradeinDay = false;
					}
					for (int i = 0; i < alist.size(); i++) {
						Action act = alist.get(i);
						if (act.inOrOut == Action.IN_ACTION
								&& act.longOrShort == Action.LONG_ACTION) {
							inPrice[2] = act.price;
							longOrShort[2] = Action.LONG_ACTION;
							/* 開盤即買進 */
							if (moreThanOneTradeinDay)
							{							
								;				
							}
							else {
							  currentProfit += currentLot
									* (allStockPrices.get(iterString).ohlc.close - allStockPrices
											.get(iterString).ohlc.open);
							}
							numInHand++;
						} else if (act.inOrOut == Action.OUT_ACTION
								&& act.longOrShort == Action.LONG_ACTION) {
							if (act.reason == Action.STOP_LOSS_REASON) {
								/* 尾盤賣出 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
							} else if (act.reason == Action.STOP_PROFIT_REASON
									|| act.reason == Action.TREND_REVERT_REASON) {
								/* 開盤即賣出 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							} else if (act.reason == Action.FORCE_STOP_LOSS_REASON) {
								/* 盤中強制出場 */
								double sellprice = inPrice[2] - forceLoss[2];
								if (moreThanOneTradeinDay)
								{
									currentProfit -= currentLot*forceLoss[2];
								}
								else {
									currentProfit += currentLot							
										* (sellprice - prevClosePrice);
								}
							} else if (act.reason == Action.FORCE_STOP_LOSS_AT_START_REASON) {
								/* 盤中開盤強制出場 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							}
							inPrice[2] = -1;
							longOrShort[2] = -1;
							numInHand--;
						} else if (act.inOrOut == Action.IN_ACTION
								&& act.longOrShort == Action.SHORT_ACTION) {
							/* 開盤即放空 */
							inPrice[2] = act.price;
							longOrShort[2] = Action.SHORT_ACTION;
							if (moreThanOneTradeinDay)
							{
								;					
							}
							else  {
							currentProfit -= currentLot
									* (allStockPrices.get(iterString).ohlc.close - allStockPrices
											.get(iterString).ohlc.open);
							}							numInHand--;
						} else if (act.inOrOut == Action.OUT_ACTION
								&& act.longOrShort == Action.SHORT_ACTION) {
							if (act.reason == Action.STOP_LOSS_REASON) {
								/* 尾盤回補 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
							} else if (act.reason == Action.STOP_PROFIT_REASON
									|| act.reason == Action.TREND_REVERT_REASON) {
								/* 開盤即空單回補 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							} else if (act.reason == Action.FORCE_STOP_LOSS_REASON) {
								/* 盤中強制出場 */
								double sellprice = inPrice[2] + forceLoss[2];
								if (moreThanOneTradeinDay)
								{
									currentProfit -= currentLot*forceLoss[2];
									//currentProfit += currentLot
									//* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);								
								}
								else {							
								  currentProfit -= currentLot
										* (sellprice - prevClosePrice);
								}
							} else if (act.reason == Action.FORCE_STOP_LOSS_AT_START_REASON) {
								/* 盤中開盤強制出場 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							}
							inPrice[2] = -1;
							longOrShort[2] = -1;
							numInHand++;
						} else {
							System.err.println("ERROR TYPE IV");
							System.exit(0);
						}
					}
				} else {
					/* 此日無動作,保有原單 */
					if (inPrice[2] < 0 || longOrShort[2] == -1) {
						; // do nothing
					} else if (longOrShort[2] == Action.LONG_ACTION)
						currentProfit += currentLot
								* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
					else if (longOrShort[2] == Action.SHORT_ACTION)
						currentProfit -= currentLot
								* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
					else if (longOrShort[2] == 0) {
						; // do nothing
					} else {
						System.err.println("ERROR TYPE III");
					}
				}

			}
			if (map3 != null) {
				if (map3.containsKey(iterString)) {
	                boolean moreThanOneTradeinDay =false;
					ArrayList<Action> alist = map3.get(iterString);
					if (alist.size()>1) { /*開盤買進,盤中即出場*/
						moreThanOneTradeinDay = true;
					}
					else {
						moreThanOneTradeinDay = false;
					}
					for (int i = 0; i < alist.size(); i++) {
						Action act = alist.get(i);
						if (act.inOrOut == Action.IN_ACTION
								&& act.longOrShort == Action.LONG_ACTION) {
							inPrice[3] = act.price;
							longOrShort[3] = Action.LONG_ACTION;
							/* 開盤即買進 */
							if (moreThanOneTradeinDay)
							{							
								;				
							}
							else {
							  currentProfit += currentLot
									* (allStockPrices.get(iterString).ohlc.close - allStockPrices
											.get(iterString).ohlc.open);
							}
							numInHand++;
						} else if (act.inOrOut == Action.OUT_ACTION
								&& act.longOrShort == Action.LONG_ACTION) {
							if (act.reason == Action.STOP_LOSS_REASON) {
								/* 尾盤賣出 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
							} else if (act.reason == Action.STOP_PROFIT_REASON
									|| act.reason == Action.TREND_REVERT_REASON) {
								/* 開盤即賣出 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							} else if (act.reason == Action.FORCE_STOP_LOSS_REASON) {
								/* 盤中強制出場 */
								double sellprice = inPrice[3] - forceLoss[3];
								if (moreThanOneTradeinDay)
								{
									currentProfit -= currentLot*forceLoss[3];
								}
								else {
									currentProfit += currentLot							
										* (sellprice - prevClosePrice);
								}
							} else if (act.reason == Action.FORCE_STOP_LOSS_AT_START_REASON) {
								/* 盤中開盤強制出場 */
								currentProfit += currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							}
							inPrice[3] = -1;
							longOrShort[3] = -1;
							numInHand--;
						} else if (act.inOrOut == Action.IN_ACTION
								&& act.longOrShort == Action.SHORT_ACTION) {
							/* 開盤即放空 */
							inPrice[3] = act.price;
							longOrShort[3] = Action.SHORT_ACTION;
							if (moreThanOneTradeinDay)
							{
								;					
							}
							else  {
							currentProfit -= currentLot
									* (allStockPrices.get(iterString).ohlc.close - allStockPrices
											.get(iterString).ohlc.open);
							}							numInHand--;
						} else if (act.inOrOut == Action.OUT_ACTION
								&& act.longOrShort == Action.SHORT_ACTION) {
							if (act.reason == Action.STOP_LOSS_REASON) {
								/* 尾盤回補 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
							} else if (act.reason == Action.STOP_PROFIT_REASON
									|| act.reason == Action.TREND_REVERT_REASON) {
								/* 開盤即空單回補 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							} else if (act.reason == Action.FORCE_STOP_LOSS_REASON) {
								/* 盤中強制出場 */
								double sellprice = inPrice[3] + forceLoss[3];
								if (moreThanOneTradeinDay)
								{
									currentProfit -= currentLot*forceLoss[3];
									//currentProfit += currentLot
									//* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);								
								}
								else {							
								  currentProfit -= currentLot
										* (sellprice - prevClosePrice);
								}
							} else if (act.reason == Action.FORCE_STOP_LOSS_AT_START_REASON) {
								/* 盤中開盤強制出場 */
								currentProfit -= currentLot
										* (allStockPrices.get(iterString).ohlc.open - prevClosePrice);
							}
							inPrice[3] = -1;
							longOrShort[3] = -1;
							numInHand++;
						} else {
							System.err.println("ERROR TYPE IV");
							System.exit(0);
						}
					}
				} else {
					/* 此日無動作,保有原單 */
					if (inPrice[3] < 0 || longOrShort[3] == -1) {
						; // do nothing
					} else if (longOrShort[3] == Action.LONG_ACTION)
						currentProfit += currentLot
								* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
					else if (longOrShort[3] == Action.SHORT_ACTION)
						currentProfit -= currentLot
								* (allStockPrices.get(iterString).ohlc.close - prevClosePrice);
					else if (longOrShort[3] == 0) {
						; // do nothing
					} else {
						System.err.println("ERROR TYPE III");
					}
				}
			}

			if (numInHand > 4 || numInHand < -4) {
				System.err.println("ERROR TYPE 7");
				// System.exit(0);
			}
			dayMap.put(iterString, new Double(currentProfit));

			System.out.println(iterString + ":" + numInHand + ":" + currentLot
					+ ":" + currentProfit);
			writer.write(iterString + "," + numInHand + "," + currentLot + ","
					+ currentProfit + "\n");
			prevClosePrice = allStockPrices.get(iterString).ohlc.close;
			iterTime.add(Calendar.DATE, 1);
		}
		writer.close();
		
		Trade.analyzeTradeList(tradeList0);
		if (tradeList1.size()>0) 
		  Trade.analyzeTradeList(tradeList1);
	}

	public DailyStopProfitLossEvaluator() throws IOException {
		exec();
		
		DateArrayAnalyzer analyzer = new DateArrayAnalyzer(dayMap);

		try {
			analyzer.analyzeBaseStatistic();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private TreeMap<String, ArrayList<Action>> readFile(String fn, ArrayList<Trade> tradeList) {		
		TreeMap<String, ArrayList<Action>> map = new TreeMap<String, ArrayList<Action>>();
		try {
			BufferedReader reader = new BufferedReader(new FileReader(fn));
			String line;
			Trade newTrade = null;
			while ((line = reader.readLine()) != null) {
				if (line.startsWith("1") || line.startsWith("2")) {
					String[] lines = new String[2];
					lines[0] = line;
					lines[1] = reader.readLine();
					Action act = parseAction(lines);
					if (tradeList != null) {
					  if (act.inOrOut == Action.IN_ACTION) {
						newTrade = new Trade(act.longOrShort, act.price, act.date);
					  }
					  else if (act.inOrOut == Action.OUT_ACTION) {
						newTrade.closeTrade(act.price, act.date);
						tradeList.add(newTrade);
					  }
					}
					if (map.containsKey(df.format(act.date.getTime()))) {
						map.get(df.format(act.date.getTime())).add(act);
					} else {
						ArrayList<Action> alist = new ArrayList<Action>();
						alist.add(act);
						map.put(df.format(act.date.getTime()), alist);
					}
				}
			}
			reader.close();
		} catch (IOException e) {
			System.out.println(e);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Read " + map.size() + " action");
		return map;
	}

	static int prevActionType = -1;

	public Action parseAction(String[] lines) throws ParseException {
		Action act = new Action();
		// System.out.println(lines[0]);
		// System.out.println(lines[1]);
		StringTokenizer token = new StringTokenizer(lines[0], " ,");

		act.date = new GregorianCalendar();
		act.date.setTime(df.parse(token.nextToken()));
		token = new StringTokenizer(lines[1], ",");
		String dowhat = token.nextToken();
		if (dowhat.equals("出場")) {
			act.inOrOut = Action.OUT_ACTION;
			act.longOrShort = prevActionType;
			StringTokenizer token1 = new StringTokenizer(token.nextToken(), " ");
			token1.nextToken();
			act.price = Double.parseDouble(token1.nextToken());
			token1 = new StringTokenizer(token.nextToken(), "：");
			token1.nextToken();
			String r = token1.nextToken();
			if (r.startsWith("停損")) {
				act.reason = Action.STOP_LOSS_REASON;
			} else if (r.startsWith("停利")) {
				act.reason = Action.STOP_PROFIT_REASON;
			} else if (r.startsWith("盤中開盤")) {
				act.reason = Action.FORCE_STOP_LOSS_AT_START_REASON;
			} else if (r.startsWith("盤中強制")) {
				act.reason = Action.FORCE_STOP_LOSS_REASON;
			} else {
				act.reason = Action.TREND_REVERT_REASON;
			}
		} else if (dowhat.equals("進場")) {
			act.inOrOut = Action.IN_ACTION;
			token.nextToken();
			token.nextToken();
			String isLongStr = token.nextToken();
			//System.out.println(isLongStr);
			StringTokenizer isLongToken = new StringTokenizer(isLongStr, " ()");
			String isLong = isLongToken.nextToken();
			if (isLong.equals("做多")) {
				act.longOrShort = Action.LONG_ACTION;
				prevActionType = Action.LONG_ACTION;
			} else if (isLong.equals("做空")) {
				act.longOrShort = Action.SHORT_ACTION;
				prevActionType = Action.SHORT_ACTION;
			} else {
				assert (true);
			}
			if (isLongToken.hasMoreTokens())
			{
				if (isLongToken.nextToken().equals("昨單續留")) {
					if (act.longOrShort == Action.LONG_ACTION)
						act.longOrShort = Action.LONG_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN;
					if (act.longOrShort == Action.SHORT_ACTION)
						act.longOrShort = Action.SHORT_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN;
			    }
			}
			
			StringTokenizer token1 = new StringTokenizer(token.nextToken(), " ");
			token1.nextToken();
			act.price = Double.parseDouble(token1.nextToken());
		} else {
			assert (true);
		}

		return act;
	}

	public static void main(String[] args) {
		try {
			new DailyStopProfitLossEvaluator();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	class DateArrayAnalyzer {
		int LOOK_DAY_THRESHOLD = 10;
		TreeMap<String, Double> dayMap;
		TreeMap<String, Double> maxMap = new TreeMap<String, Double>();
		TreeMap<String, Double> minMap = new TreeMap<String, Double>();

		public DateArrayAnalyzer(TreeMap<String, Double> dayMap) {
			this.dayMap = dayMap;
		}

		public void analyzeBaseStatistic() throws ParseException, IOException {
			BufferedWriter writer = new BufferedWriter(new FileWriter(
					"tmp/year_evaluate.csv"));
			String leastDayInDB = dayMap.lastKey();
			StatCalc sixMonthProfit = new StatCalc();
			StatCalc oneYearProfit = new StatCalc();
			StatCalc twoYearProfit = new StatCalc();
			StatCalc threeYearProfit = new StatCalc();

			StatCalc sixMonthMin = new StatCalc();
			StatCalc oneYearMin = new StatCalc();
			StatCalc twoYearMin = new StatCalc();
			StatCalc threeYearMin = new StatCalc();

			StatCalc sixMonthMax = new StatCalc();
			StatCalc oneYearMax = new StatCalc();
			StatCalc twoYearMax = new StatCalc();
			StatCalc threeYearMax = new StatCalc();

			SimpleDateFormat df1 = new SimpleDateFormat("yyyyMMdd");
			GregorianCalendar sixMonthDay = new GregorianCalendar();
			GregorianCalendar oneYearDay = new GregorianCalendar();
			GregorianCalendar twoYearDay = new GregorianCalendar();
			GregorianCalendar threeYearDay = new GregorianCalendar();
			GregorianCalendar leastDB = new GregorianCalendar();
			leastDB.setTime(df.parse(leastDayInDB));
			Iterator<String> iter = dayMap.keySet().iterator();

			writer
					.write("Date,SixMonthDuringMin,SixMonthDuringMax,SixMonthProfit,OneYearDuringMin,OneYearDuringMax,OneYearProfit,"
							+ "TwoYearDuringMin,TwoYearDuringMax,TwoYearProfit,ThreeYearDuringMin,ThreeYearDuringMax,ThreeYearProfit\n");
			while (iter.hasNext()) {
				String today = iter.next();
				if (!iter.hasNext()) {
					continue;
				}
				// System.out.println(today);
				if (!dayMap.containsKey(today)) {
					continue;
				}
				double todayVal = dayMap.get(today);
				writer.write(today + ",");
				Date d = df.parse(today);
				sixMonthDay.setTime(d);
				oneYearDay.setTime(d);
				twoYearDay.setTime(d);
				threeYearDay.setTime(d);
				sixMonthDay.add(Calendar.MONTH, 6);
				oneYearDay.add(Calendar.YEAR, 1);
				twoYearDay.add(Calendar.YEAR, 2);
				threeYearDay.add(Calendar.YEAR, 3);
				String[] between;
				StatCalc tmp;
				if (!sixMonthDay.after(leastDB)) {
					between = DateUtil.getDateBetween(df1.format(d), df1
							.format(sixMonthDay.getTime()));
					tmp = new StatCalc();
					for (int i = 0; i < between.length; i++) {
						String b = df.format(df1.parse(between[i]));
						if (dayMap.containsKey(b)) {
							tmp.enter(dayMap.get(b) - todayVal);
						}
					}
					sixMonthProfit.enter(tmp.getLeastNum());
					sixMonthMin.enter(tmp.getMin());
					sixMonthMax.enter(tmp.getMax());
					writer.write(tmp.getMin() + "," + tmp.getMax() + ","
							+ tmp.getLeastNum() + ",");
				} else {
					writer.write(",,,");
				}
				if (!oneYearDay.after(leastDB)) {
					between = DateUtil.getDateBetween(df1.format(d), df1
							.format(oneYearDay.getTime()));
					tmp = new StatCalc();
					for (int i = 0; i < between.length; i++) {
						String b = df.format(df1.parse(between[i]));
						if (dayMap.containsKey(b)) {
							tmp.enter(dayMap.get(b) - todayVal);
						}
					}
					oneYearProfit.enter(tmp.getLeastNum());
					oneYearMin.enter(tmp.getMin());
					oneYearMax.enter(tmp.getMax());
					writer.write(tmp.getMin() + "," + tmp.getMax() + ","
							+ tmp.getLeastNum() + ",");
				} else {
					writer.write(",,,");
				}
				if (!twoYearDay.after(leastDB)) {
					between = DateUtil.getDateBetween(df1.format(d), df1
							.format(twoYearDay.getTime()));
					tmp = new StatCalc();
					for (int i = 0; i < between.length; i++) {
						String b = df.format(df1.parse(between[i]));
						if (dayMap.containsKey(b)) {
							tmp.enter(dayMap.get(b) - todayVal);
						}
					}
					twoYearProfit.enter(tmp.getLeastNum());
					twoYearMin.enter(tmp.getMin());
					twoYearMax.enter(tmp.getMax());
					writer.write(tmp.getMin() + "," + tmp.getMax() + ","
							+ tmp.getLeastNum() + ",");
				} else {
					writer.write(",,,");
				}
				if (!threeYearDay.after(leastDB)) {
					between = DateUtil.getDateBetween(df1.format(d), df1
							.format(threeYearDay.getTime()));
					tmp = new StatCalc();
					for (int i = 0; i < between.length; i++) {
						String b = df.format(df1.parse(between[i]));
						if (dayMap.containsKey(b)) {
							tmp.enter(dayMap.get(b) - todayVal);
						}
					}
					threeYearProfit.enter(tmp.getLeastNum());
					threeYearMin.enter(tmp.getMin());
					threeYearMax.enter(tmp.getMax());

					writer.write(tmp.getMin() + "," + tmp.getMax() + ","
							+ tmp.getLeastNum() + "\n");
				} else {
					writer.write(",,\n");
				}
			}

			String line = "六個月平均獲利:" + sixMonthProfit.getMean() + "\n六個月最少獲利:"
					+ sixMonthProfit.getMin() + "\n六個月最高獲利:"
					+ sixMonthProfit.getMax() + "\n一年平均獲利:"
					+ oneYearProfit.getMean() + "\n一年最少獲利:"
					+ oneYearProfit.getMin() + "\n一年最高獲利:"
					+ oneYearProfit.getMax() + "\n兩年平均獲利:"
					+ twoYearProfit.getMean() + "\n兩年最少獲利:"
					+ twoYearProfit.getMin() + "\n兩年月最高獲利:"
					+ twoYearProfit.getMax() + "\n三年平均獲利:"
					+ threeYearProfit.getMean() + "\n三年最少獲利:"
					+ threeYearProfit.getMin() + "\n三年最高獲利:"
					+ threeYearProfit.getMax() + "\n";
			System.out.println(line);
			writer.write(line);
			writer.close();
		}

		/**
		 * TODO
		 */
		public void analyzePeak() {
			Iterator<String> iter = maxMap.keySet().iterator();
			while (iter.hasNext()) {
				String d1 = iter.next();
				maxMap.get(d1).doubleValue();
			}
		}

		/**
		 * TODO
		 * 
		 * @throws ParseException
		 */
		public void baseAnalyzer() throws ParseException {
			SimpleDateFormat df1 = new SimpleDateFormat("yyyyMMdd");
			GregorianCalendar afterDay = new GregorianCalendar();
			GregorianCalendar beforeDay = new GregorianCalendar();
			Iterator<String> iter = dayMap.keySet().iterator();
			while (iter.hasNext()) {
				boolean isMax = true;
				boolean isMin = true;
				String today = iter.next();
				double todayVal = dayMap.get(today);
				Date d = df.parse(today);
				beforeDay.setTime(d);
				afterDay.setTime(d);
				beforeDay.add(Calendar.DATE, -LOOK_DAY_THRESHOLD);
				afterDay.add(Calendar.DATE, LOOK_DAY_THRESHOLD);

				String[] between = DateUtil.getDateBetween(df1.format(beforeDay
						.getTime()), df1.format(afterDay.getTime()));
				for (int i = 0; i < between.length; i++) {
					String b = df.format(df1.parse(between[i]));
					if (dayMap.containsKey(b)) {
						if (isMax && dayMap.get(b).doubleValue() > todayVal) {
							isMax = false;
						}
						if (isMin && dayMap.get(b).doubleValue() < todayVal) {
							isMin = false;
						}
					}
				}
				if (isMax) {
					maxMap.put(today, todayVal);
				}
				if (isMin) {
					minMap.put(today, todayVal);
				}
			}
		}
	}
}
